﻿using System.Collections.Generic;
using UnityEngine;

namespace IQIGame.Onigao.Game
{
    public class UIItemPool<T> : IUIList where T : UIBaseNode, new()
    {
        public GameObject prefab { get; private set; }

        public List<T> listItems { get; private set; }
        protected Stack<T> poolItems { get; set; }
        
        public int Count => listItems?.Count ?? 0;

        private UIBaseWindow _belongWindow = null;
        public UIItemPool(GameObject prefab, UIBaseWindow baseWindow = null, bool hidePrefab = true)
        {
            this.prefab = prefab;
            this._belongWindow = baseWindow;
            if (hidePrefab)
            {
                this.prefab.SetActive(false);
            }

            this.listItems = new List<T>();
            this.poolItems = new Stack<T>();
        }

        public void HideAll()
        {
            foreach (var item in listItems)
            {
                item.Hide();
                this.poolItems.Push(item);
            }
            listItems.Clear();
        }

        public void HideAfter(int indexBegHide)
        {
            if (indexBegHide < 0 || indexBegHide > this.listItems.Count)
                return;
            for (int i = this.listItems.Count - 1; i >= indexBegHide; i--)
            {
                this.HideOne(this.listItems[i]);
            }
        }

        public void HideOne(T item)
        {
            if (listItems.Remove(item))
            {
                item.Hide();
                this.poolItems.Push(item);
            }
        }

        public T GetOne(bool isShow = true)
        {
            if (this.poolItems.Count > 0)
            {
                var item = this.poolItems.Pop();
                if (isShow)
                {
                    item.Show();
                }
                item.transform.SetAsLastSibling();
                this.listItems.Add(item);
                return item;
            }
            var go = GameObject.Instantiate(this.prefab, this.prefab.transform.parent);
            if (isShow)
            {
                go.SetActive(true);
            }
            var newitem = new T();
            newitem.Init(go, this._belongWindow);
            this.listItems.Add(newitem);
            return newitem;
        }

        public bool TryGetFirst(out T item)
        {
            if (this.listItems.Count > 0)
            {
                item = this.listItems[0];
                return true;
            }
            item = default(T);
            return false;
        }

        public T GetActiveOne(int index)
        {
            if (index < 0)
                return null;
            var cnt = this.listItems.Count;
            if (cnt <= index)
                return null;
            return this.listItems[index];
        }

        public void Clear()
        {
            this._belongWindow = null;
            this.HideAll();
            while (this.poolItems.Count > 0)
            {
                this.poolItems.Pop().Dispose();
            }
        }
    }
}
